using System;
using System.Text.RegularExpressions;

namespace Framework
{
    // http://www.regexlib.com/CheatSheet.htm
    public static class RegExUtil
    {
        private static Regex[] StandardRegularExpressions { get; set; }

        #region GetRegEx
        /// <summary> 
        /// Get a predefined regular expression
        /// </summary>
        /// <param name="regularExpressionId">Id of the regular expression to return
        /// </param>
        /// <returns>RegEx</returns>
        public static Regex GetRegEx(RegularExpressionType regularExpressionId)
        {
            // Setup StandardRegularExpressions array on first call
            if (StandardRegularExpressions == null)
            {
                StandardRegularExpressions =
                   new Regex[Enum.GetNames(typeof(RegularExpressionType)).Length];
            }

            int index = (int)regularExpressionId;

            // Setup [index] regular expression if first time
            if (StandardRegularExpressions[index] == null)
            {   
                StandardRegularExpressions[index] = GetStandardRegularExpression(regularExpressionId);
            }

            return StandardRegularExpressions[index];
        }
        #endregion

        #region GetMatchRegEx
        /// <summary> 
        /// Get a match object based on a predefined regular expression
        /// </summary>
        /// <param name="regularExpressionId">Id of the regular expression to return</param>
        /// <param name="text">Text to match on</param>
        /// <returns>Match</returns>
        public static Match GetMatchRegEx(RegularExpressionType regularExpressionId, string text)
        {
            return GetRegEx(regularExpressionId).Match(text);
        }
        #endregion

        #region MatchReplaceWith
        /// <summary>
        /// Create match evaluator replace with
        /// </summary>
        /// <returns></returns>
        public static MatchEvaluatorReplaceWith CreateMatchEvaluatorReplaceWith()
        {
            return new MatchEvaluatorReplaceWith();
        }

        public static MatchEvaluatorReplaceWith CreateMatchEvaluatorReplaceWith(string replacementValue)
        {
            MatchEvaluatorReplaceWith result = new MatchEvaluatorReplaceWith();

            result.ReplacementValue = replacementValue;

            return result;
        }
        #endregion

        #region StandardRegularExpression
        /// <summary>
        /// Predefined list of standard regular expressions
        /// </summary>
        /// <param name="regularExpressionId"></param>
        /// <returns></returns>
        private static Regex GetStandardRegularExpression(RegularExpressionType regularExpressionId)
        {
            // List of RegEx's
            // http://regexlib.com/ 
            // http://regexlib.com/CheatSheet.htm
            // http://aspnet.4guysfromrolla.com/articles/022603-1.aspx
            // http://www.amk.ca/python/howto/regex/regex.html#SECTION000300000000000000000

            // Another URL plus content extractor plus some other stuff
            // See: http://aspalliance.com/233
            // <A HREF='(?[^']+)'[\s]*?>(?<strheadline>[^<]+)</A>[\s\w\W]*?<BR>(?<strsummary>[^<]+)<

            switch (regularExpressionId)
            {
                case RegularExpressionType.UrlExtractor:
                    {  // Refer to http://www.standardio.org/article.aspx?id=173 for help
                        return new Regex(
                           @"(?:href\s*=)(?:[\s""']*)(?!#|mailto|location.|javascript|.*css|.*this\.)(?<url>.*?)(?:[\s>""'])"
                           , RegexOptions.IgnoreCase);
                    }
                case RegularExpressionType.SrcExtractor:
                    {
                        return new Regex(
                           @"(?:src\s*=)(?:[\s""']*)(?<url>.*?)(?:[\s>""'])"
                           , RegexOptions.IgnoreCase);
                    }
                case RegularExpressionType.MacroPropertyBrace:
                    {
                        return new Regex(
                           //@"([$][{])(?<prop>[0-9a-zA-Z._,|%:= ]*)([}])"
                           @"([$][{])(?<prop>.*?)([}])"
                           , RegexOptions.IgnoreCase);
                    }
                case RegularExpressionType.MacroPropertySquare:
                    {
                        return new Regex(
                           @"([$]\[)(?<prop>[0-9a-zA-Z._,:= ]*)(\])"
                           , RegexOptions.IgnoreCase);
                    }
                case RegularExpressionType.MacroPropertyHash:
                    {
                        return new Regex(
                           @"([$][#])(?<prop>[0-9a-zA-Z._,:= ]*)([#])"
                           , RegexOptions.IgnoreCase);
                    }
                case RegularExpressionType.MacroPropertyRound:
                    {
                        return new Regex(
                           @"([$][(])(?<prop>[0-9a-zA-Z._,:= ]*)([)])"
                           , RegexOptions.IgnoreCase);
                    }
                case RegularExpressionType.Email:
                    {
                        var emailRegEx =
                            "^((?>[a-zA-Z\\d!#$%&'*+\\-/=?^_`{|}~]+\\x20*|\"((?=[\\x01-\\x7f])[^\"\\\\]|\\\\[\\x01-\\x7f])*\"\\x20*)*(?<angle><))?((?!\\.)(?>\\.?[a-zA-Z\\d!#$%&'*+\\-/=?^_`{|}~]+)+|\"((?=[\\x01-\\x7f])[^\"\\\\]|\\\\[\\x01-\\x7f])*\")@(((?!-)[a-zA-Z\\d\\-]+(?<!-)\\.)+[a-zA-Z]{2,}|\\[(((?(?<!\\[)\\.)(25[0-5]|2[0-4]\\d|[01]?\\d?\\d)){4}|[a-zA-Z\\d\\-]*[a-zA-Z\\d]:((?=[\\x01-\\x7f])[^\\\\\\[\\]]|\\\\[\\x01-\\x7f])+)\\])(?(angle)>)$";
                        return new Regex(emailRegEx);
                           //@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" + @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" + @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
                           // Davo: This is the one that DNN was using 
                           // "^((?>[a-zA-Z\\d!#$%&'*+\\-/=?^_`{|}~]+\\x20*|\"((?=[\\x01-\\x7f])[^\"\\\\]|\\\\[\\x01-\\x7f])*\"\\x20*)*(?<angle><))?((?!\\.)(?>\\.?[a-zA-Z\\d!#$%&'*+\\-/=?^_`{|}~]+)+|\"((?=[\\x01-\\x7f])[^\"\\\\]|\\\\[\\x01-\\x7f])*\")@(((?!-)[a-zA-Z\\d\\-]+(?<!-)\\.)+[a-zA-Z]{2,}|\\[(((?(?<!\\[)\\.)(25[0-5]|2[0-4]\\d|[01]?\\d?\\d)){4}|[a-zA-Z\\d\\-]*[a-zA-Z\\d]:((?=[\\x01-\\x7f])[^\\\\\\[\\]]|\\\\[\\x01-\\x7f])+)\\])(?(angle)>)$";
                    }
                case RegularExpressionType.PhoneNumber:
                    {
                        var emailRegEx =
                            @"^[0-9]{10}$|^\(0[1-9]{1}\)[0-9]{8}$|^[0-9]{8}$|^[0-9]{4}[ ][0-9]{3}[ ][0-9]{3}$|^\(0[1-9]{1}\)[ ][0-9]{4}[ ][0-9]{4}$|^[0-9]{4}[ ][0-9]{4}$";

                        emailRegEx =
                            @"^\({0,1}((0|\+61)(2|4|3|7|8)){0,1}\){0,1}(\ |-){0,1}[0-9]{2}(\ |-){0,1}[0-9]{2}(\ |-){0,1}[0-9]{1}(\ |-){0,1}[0-9]{3}$";
                        return new Regex(emailRegEx);
                    }
                case RegularExpressionType.CreditCardName:
                    {
                        //               return new Regex( 
                        //                  @"(([A-Z]+ )(([A-Z]+ )$)(([A-Z]+ )$)(([A-Z]+ )$)([A-Z]+))" );
                        return new Regex(
                             @"^(([A-Z]+)(\s$))*$");
                        //                  @"^(([A-Z]+)(\s$))*" );
                    }
            }

            return null;
        }
        #endregion
    }

    #region BaseMatchEvaluator
    public abstract class BaseMatchEvaluator
    {
        #region C'tor
        public BaseMatchEvaluator()
        {
        }
        #endregion

        #region Evaluate
        public abstract string Evaluate(Match m);
        #endregion

        #region Evaluator
        public MatchEvaluator Evaluator
        {
            get { return new MatchEvaluator(this.Evaluate); }
        }
        #endregion
    }
    #endregion

    #region MatchEvaluatorReplaceWith (Match Evaluator)
    public class MatchEvaluatorReplaceWith : BaseMatchEvaluator
    {
        #region C'tor
        public MatchEvaluatorReplaceWith()
        {
            ReplacementValue = String.Empty;
        }
        #endregion

        #region ReplacementValue
        private string m_replacementValue;

        public string ReplacementValue
        {
            get { return m_replacementValue; }
            set { m_replacementValue = value; }
        }
        #endregion

        #region Evaluate
        public override string Evaluate(Match m)
        {
            return ReplacementValue;
        }
        #endregion
    }
    #endregion

}
